home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archivers / XpkDisk / xdclear.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  14KB  |  625 lines

  1. /*
  2.  * On a clear disk you can seek forever...
  3.  *
  4.  * Clear out all unused blocks on a disk, and if a whole track is
  5.  * unused, delete the appropriate track file.
  6.  *
  7.  * $Id: xdclear.c,v 1.3 1995/04/08 20:23:48 Rhialto Exp $
  8.  * $Log: xdclear.c,v $
  9.  * Revision 1.3  1995/04/08  20:23:48  Rhialto
  10.  * Add/correct version strings.
  11.  *
  12.  * Revision 1.2  1995/04/02  14:58:51  Rhialto
  13.  * Take LowCyl into account. This fixes partitions that don't start at cyl 0.
  14.  * Change ETD_* commands to TD_* because the A4000's scsi.device does not
  15.  * understand them.
  16.  * Fix bogus exit status.
  17.  *
  18.  * Revision 1.1  1993/11/08  13:23:03  Rhialto
  19.  * Initial revision
  20.  *
  21.  * (C) Copyright 1993,1995 by Olaf 'Rhialto' Seibert. All rights reserved.
  22.  */
  23.  
  24. #include "xpkdisk.h"
  25.  
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <dos/dos.h>
  30. #include <dos/filehandler.h>
  31.  
  32. extern struct DosLibrary *DOSBase;
  33. extern struct ExecBase *SysBase;
  34.  
  35. static const char idString[] = "\0$VER: xdClear " STR(VERSION) "." STR(REVISION) "\r\n";
  36. static const char rcsId[] = "$Id: xdclear.c,v 1.3 1995/04/08 20:23:48 Rhialto Exp $";
  37.  
  38. struct FileSysStartupMsg Fssm;
  39. struct DosEnvec De;
  40. struct IOExtTD *Io;
  41. struct MsgPort *Port;
  42. struct MsgPort *HandlerPort;
  43. ULONG        NumTracks;
  44. ULONG        MaxKey;
  45. ULONG        RootBlockKey;
  46. ULONG           *RootBlock;
  47. ULONG        BitsPerBitmapBlock;
  48. ULONG        BMBlocksPerBitmapExtBlock;
  49. ULONG        BitmapBlockNr = -2;
  50. ULONG           *BitmapBlock;
  51. ULONG        BitmapExtBlockNr = -1;
  52. ULONG           *BitmapExtBlock;
  53. ULONG           *ZeroBlock;
  54. ULONG        LowTrack;
  55. ULONG        Offset;
  56. int        XpkDisk;
  57. int        Pretend;
  58. int        Verbose;
  59.  
  60. int        SectorsCleared;
  61. int        SectorsReallyCleared;
  62. int        TracksDeleted;
  63. int        TracksReallyDeleted;
  64.  
  65. #define debug(x)    printf x
  66. #define debug0(x)
  67.  
  68. #define SIZE    De.de_SizeBlock
  69.  
  70. #define BM_BLOCKS_PER_ROOTBLOCK     ((-25)-(-49)+1)
  71. #define BM_BLOCKS_PER_BMEBLOCK        (SIZE - 1)
  72.  
  73. int
  74. GetKey(ULONG key, ULONG *buffer)
  75. {
  76.     long offset = Offset + sizeof(ULONG) * SIZE * key;
  77.  
  78.     Io->iotd_Req.io_Command = CMD_READ;    /* ETD */
  79.     Io->iotd_Req.io_Offset = offset;
  80.     Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
  81.     Io->iotd_Req.io_Data = (char *)buffer;
  82.  
  83.     if (DoIO((struct IORequest *)Io)) {
  84.     printf("Read error %d on sector %d (offset 0x%lx bytes, %dK, %dM)!\n",
  85.         Io->iotd_Req.io_Error, key, offset, offset / 1024, offset / (1024 * 1024));
  86.     if (Verbose) {
  87.         printf("device=\"%s\" unit %d\n", Fssm.fssm_Device, Fssm.fssm_Unit);
  88.     }
  89.     return Io->iotd_Req.io_Error;
  90.     }
  91.     return 0;
  92. }
  93.  
  94. int
  95. PutKey(ULONG key, ULONG *buffer)
  96. {
  97.     Io->iotd_Req.io_Command = CMD_WRITE;    /* ETD */
  98.     Io->iotd_Req.io_Offset = Offset + sizeof(ULONG) * SIZE * key;
  99.     Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
  100.     Io->iotd_Req.io_Data = (char *)buffer;
  101.  
  102.     if (DoIO((struct IORequest *)Io)) {
  103.     printf("Write error %d on sector %d!\n",
  104.         Io->iotd_Req.io_Error, key);
  105.     return Io->iotd_Req.io_Error;
  106.     }
  107.     return 0;
  108. }
  109.  
  110. /*
  111.  * All checksums make the block add to 0.
  112.  */
  113. int
  114. CheckSum(ULONG *buffer)
  115. {
  116.     int         i;
  117.     ULONG        sum = 0;
  118.  
  119.     for (i = SIZE; i > 0; i--)
  120.     sum += *buffer++;
  121.  
  122.     return sum? 0 : 1;
  123. }
  124.  
  125. int
  126. GetBitmapExtBlock(ULONG blocknr)
  127. {
  128.     if (blocknr != BitmapExtBlockNr) {
  129.     ULONG        key;
  130.     ULONG        keynr;
  131.  
  132.     if (blocknr < BitmapExtBlockNr || BitmapExtBlockNr == (ULONG)-1) {
  133.         key = RootBlock[SIZE - 24];
  134.         keynr = 0;
  135.         if (Verbose >= 2)
  136.         printf("GetBitmapExtBlock %d -> first key %d\n", blocknr, key);
  137.     } else {
  138.         key = BitmapExtBlock[SIZE - 1];
  139.         keynr = BitmapExtBlockNr + 1;
  140.         if (Verbose >= 2)
  141.         printf("GetBitmapExtBlock %d -> next key %d\n", blocknr, key);
  142.     }
  143.  
  144.     while (key && keynr <= blocknr) {
  145.         GetKey(key, BitmapExtBlock);
  146.         BitmapExtBlockNr = keynr;
  147.         if (Verbose >= 2)
  148.         printf("GetBitmapExtBlock %d -> get %d key %d\n",
  149.             blocknr, keynr, key);
  150.         key = BitmapExtBlock[SIZE - 1];
  151.         keynr++;
  152.     }
  153.  
  154.     if (key == 0 && BitmapExtBlockNr != blocknr) {
  155.         debug0(("No bitmap extension block #%d!!!\n", keynr));
  156.         return -97;
  157.     }
  158.     }
  159.     return 0;
  160. }
  161.  
  162. int
  163. GetBitmapBlock(ULONG blocknr, ULONG *buffer)
  164. {
  165.     ULONG        key;
  166.  
  167.     if (blocknr < BM_BLOCKS_PER_ROOTBLOCK) {
  168.     key = RootBlock[SIZE - 49 + blocknr];
  169.     if (Verbose >= 2)
  170.         printf("GetBitmapBlock %d -> root key %d\n", blocknr, key);
  171.     } else {
  172.     ULONG        tmp =    blocknr - BM_BLOCKS_PER_ROOTBLOCK;
  173.     ULONG        bmeblocknr = tmp / BM_BLOCKS_PER_BMEBLOCK;
  174.     ULONG        offset       = tmp % BM_BLOCKS_PER_BMEBLOCK;
  175.  
  176.     if (Verbose >= 2)
  177.         printf("GetBitmapBlock %d -> extension block %d\n", blocknr, bmeblocknr);
  178.  
  179.     if ((tmp = GetBitmapExtBlock(bmeblocknr)) == 0)
  180.         key = BitmapExtBlock[offset];
  181.     else
  182.         return tmp;
  183.  
  184.     if (Verbose >= 2)
  185.         printf("GetBitmapBlock %d -> (ext'd) key %d\n", blocknr, key);
  186.     }
  187.     if (key == 0) {
  188.     debug0(("Key for BitmapBlock #%d is 0.\n", blocknr));
  189.     return -98;
  190.     }
  191.     if (GetKey(key, buffer) == 0) {
  192.     if (CheckSum(buffer) == 0) {
  193.         printf("Checksum of Bitmap Block #%d, key %d is bad!\n",
  194.            blocknr, key);
  195.         return -99;
  196.     }
  197.     return 0;
  198.     }
  199.     return Io->iotd_Req.io_Error;
  200. }
  201.  
  202. int
  203. GetBit(ULONG key)
  204. {
  205.     ULONG        blocknr;
  206.  
  207.     key -= De.de_Reserved;
  208.     blocknr = key / BitsPerBitmapBlock;
  209.  
  210.     if (blocknr != BitmapBlockNr) {
  211.     if (Verbose >= 2)
  212.         printf("GetBit %d -> BitmapBlock %d\n", key+De.de_Reserved, blocknr);
  213.  
  214.     if (blocknr == BitmapBlockNr + 1)
  215.         memcpy(BitmapBlock + 1, BitmapBlock + SIZE, (SIZE - 1) * 4);
  216.     else
  217.         GetBitmapBlock(blocknr, BitmapBlock);
  218.     if (GetBitmapBlock(blocknr + 1, BitmapBlock + SIZE) == 0) {
  219.         memmove(BitmapBlock + SIZE, BitmapBlock + SIZE + 1, (SIZE - 1) * 4);
  220.     } else {
  221.         memset(BitmapBlock + SIZE, 0, SIZE * 4);
  222.         debug0(("Zeroed 2nd bitmapblock.\n"));
  223.     }
  224.     BitmapBlockNr = blocknr;
  225.     }
  226.  
  227.     return key % BitsPerBitmapBlock;        /* bit offset */
  228. }
  229.  
  230. void
  231. ZeroOut(int key)
  232. {
  233.     debug0(("ZeroOut %d.\n", key));
  234.     SectorsCleared++;
  235.  
  236.     if (GetKey(key, ZeroBlock) == 0) {
  237.     int        i;
  238.     ULONG           *p;
  239.  
  240.     for (i = SIZE, p = ZeroBlock; i > 0; i--, p++) {
  241.         if (*p != 0) {
  242.         for (; i > 0; i--, p++)
  243.             *p = 0;
  244.         if (!Pretend)
  245.             PutKey(key, ZeroBlock);
  246.         SectorsReallyCleared++;
  247.         break;
  248.         }
  249.     }
  250.     }
  251. }
  252.  
  253. void
  254. ZeroTrack(int track)
  255. {
  256.     char        name[64];
  257.     ULONG        i;
  258.  
  259.     TracksDeleted++;
  260.     i = sprintf(name, XPKDISKDIR "Unit%lx/", Fssm.fssm_Unit);
  261.     NewName(&name[i], LowTrack + track);
  262.     if (i = Lock(name, SHARED_LOCK)) {
  263.     UnLock(i);
  264.     TracksReallyDeleted++;
  265.     printf("Delete %s.\n", name);
  266.     if (!Pretend)
  267.         DeleteFile(name);
  268.     }
  269. }
  270.  
  271. LONG
  272. min(LONG a, LONG b)
  273. {
  274.     return a < b? a: b;
  275. }
  276.  
  277. void
  278. CheckBits(int bitoffset, int numbits, ULONG key, int track)
  279. {
  280.     int         longindex;
  281.     int         longoffset;
  282.     int         bits;
  283.     ULONG       *p;
  284.     char        ones = 0;
  285.     char        zeros = 0;
  286.     ULONG        mask;
  287.     int         pass;
  288.     ULONG        mykey;
  289.  
  290.     if (Verbose >= 1) {
  291.     printf(" Track %5d... ", track);
  292.     }
  293.  
  294.     if (key == De.de_Reserved) {
  295.     /* Pretend the reserved sectors are in use */
  296.     zeros = 1;
  297.     }
  298.  
  299.     for (pass = 0 + !XpkDisk; pass < 2; pass++) {
  300.     longindex = bitoffset / 32;
  301.     longoffset = bitoffset % 32;
  302.     bits = numbits;
  303.     mykey = key;
  304.  
  305.     p = BitmapBlock + 1 + longindex;
  306.     mask = 1L << longoffset;
  307.     debug0(("Start %08lx, track %d, pass %d, mask %08lx, bits %d\n",
  308.            *p, track, pass, mask, bits));
  309.  
  310.     while (bits > 0) {
  311.         if (*p == 0xFFFFFFFF) {
  312.         if (pass > 0) {
  313.             int i = min(32-1-longoffset, bits-1);
  314.  
  315.             debug0(("bits %d, *p %x, mykey %d: ", bits, *p, mykey));
  316.             for (; i >= 0; i--) {
  317.             ZeroOut(mykey + i);
  318.             }
  319.         }
  320.         bits -= 32 - longoffset;
  321.         mask = 1;
  322.         mykey += 32 - longoffset;
  323.         longoffset = 0;
  324.         p++;
  325.         debug0(("Next  %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
  326.         ones = 1;
  327.         } else if (*p == 0) {
  328.         bits -= 32 - longoffset;
  329.         mask = 1;
  330.         mykey += 32 - longoffset;
  331.         longoffset = 0;
  332.         p++;
  333.         debug0(("Next  %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
  334.         zeros = 1;
  335.         } else {
  336.         if (*p & mask) {
  337.             /* Block free */
  338.             ones = 1;
  339.             if (pass > 0) {
  340.             debug0(("%08lx ", *p));
  341.             ZeroOut(mykey);
  342.             }
  343.         } else {
  344.             /* Block in use */
  345.             zeros = 1;
  346.         }
  347.  
  348.         bits--;
  349.         mask <<= 1;
  350.         mykey++;
  351.         if (mask == 0) {
  352.             longoffset = 0;
  353.             mask = 1;
  354.             p++;
  355.             debug0(("Next  %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
  356.         }
  357.         }
  358.     }
  359.     if (!ones || !zeros)
  360.         break;
  361.     }
  362.     if (Verbose) {
  363.     printf("%c\r", ones ? 'Z' : ' ');
  364.     fflush(stdout);
  365.     }
  366.     if (XpkDisk && !zeros)
  367.     ZeroTrack(track);
  368. }
  369.  
  370. void
  371. Clear(void)
  372. {
  373.     ULONG        key;
  374.     ULONG        nextkey;
  375.     ULONG        track;
  376.  
  377.     /* First, test the boot block for file system type */
  378.     GetKey(0, RootBlock);
  379.     if ((RootBlock[0] & 0xFFFFFF00) != 'DOS\0') {
  380.     printf("Not an AmigaDOS disk.\n");
  381.     return;
  382.     }
  383.  
  384.     /* Start at rootblock */
  385.     GetKey(RootBlockKey, RootBlock);
  386.     if (RootBlock[0] != 2 || RootBlock[SIZE-1] != ST_ROOT) {
  387.     printf("Rootblock is not a root block.\n");
  388.     return;
  389.     }
  390.     if (!CheckSum(RootBlock)) {
  391.     printf("Rootblock checksum bad.\n");
  392.     return;
  393.     }
  394.     if (RootBlock[SIZE - 50] == 0) {
  395.     printf("Bitmap valid flag not set.\n");
  396.     return;
  397.     }
  398.  
  399.     key = De.de_Reserved;
  400.     track = key / De.de_BlocksPerTrack;
  401.     nextkey = (track + 1) * De.de_BlocksPerTrack;
  402.  
  403.     if (Verbose >= 1) {
  404.     printf("This disk has %d tracks.\n", NumTracks);
  405.     }
  406.     CheckBits(GetBit(key), nextkey - key, key, track);
  407.  
  408.     track++;
  409.     key = nextkey;
  410.  
  411.     for (; key < MaxKey; key = nextkey, track++) {
  412.     int        offset;
  413.  
  414.     nextkey = key + De.de_BlocksPerTrack;
  415.     offset = GetBit(key);
  416.     CheckBits(offset, De.de_BlocksPerTrack, key, track);
  417.     chkabort();
  418.     }
  419. }
  420.  
  421. int
  422. OpenAll(char *devicename)
  423. {
  424.     int         fail = 0;
  425.  
  426.     {
  427.     struct DosList *dl;
  428.  
  429.     if (dl = LockDosList(LDF_DEVICES | LDF_READ)) {
  430.         if (dl = FindDosEntry(dl, devicename, LDF_DEVICES)) {
  431.         struct FileSysStartupMsg *fssm;
  432.         struct DosEnvec *de;
  433.  
  434.         fssm = BADDR(dl->dol_misc.dol_handler.dol_Startup);
  435.         de = BADDR(fssm->fssm_Environ);
  436.  
  437.         Fssm = *fssm;
  438.         Fssm.fssm_Device = (BSTR)((char *)BADDR(Fssm.fssm_Device) + 1);
  439.         De = *de;
  440.         HandlerPort = dl->dol_Task;
  441.         } else {
  442.         printf("No %s.\n", devicename);
  443.         fail = 1;
  444.         }
  445.         UnLockDosList(LDF_DEVICES | LDF_READ);
  446.     } else {
  447.         printf("Can't LockDosList.\n");
  448.         fail = 2;
  449.     }
  450.     }
  451.     if (fail != 0)
  452.     return fail;
  453.  
  454.     if (HandlerPort) {
  455.     DoPkt(HandlerPort, ACTION_FLUSH, 0, 0, 0, 0, 0);
  456.     DoPkt(HandlerPort, ACTION_INHIBIT, -1, 0, 0, 0, 0);
  457.     }
  458.  
  459.     if (De.de_TableSize < DE_BUFMEMTYPE)
  460.     De.de_BufMemType = MEMF_CHIP | MEMF_PUBLIC;
  461.  
  462.     Port = CreateMsgPort();
  463.     if (Port == NULL)
  464.     return 3;
  465.  
  466.     Io = (struct IOExtTD *)CreateExtIO(Port, sizeof(*Io));
  467.     if (Io == NULL)
  468.     return 4;
  469.  
  470.     if (fail = OpenDevice((char *)Fssm.fssm_Device, Fssm.fssm_Unit,
  471.            (struct IORequest *)Io, Fssm.fssm_Flags)) {
  472.     printf("Can't OpenDevice %s unit %d, error %d.\n",
  473.            Fssm.fssm_Device, Fssm.fssm_Unit, fail);
  474.     return 5;
  475.     }
  476.  
  477.     Io->iotd_Req.io_Command = TD_CHANGENUM;
  478.     fail = DoIO((struct IORequest *)Io);
  479.     if (fail) {
  480.     printf("TD_CHANGENUM: error %d\n", fail);
  481.     return 5;
  482.     }
  483.     Io->iotd_Count = Io->iotd_Req.io_Actual;
  484.  
  485.     XpkDisk = strcmp(FilePart((char *)Fssm.fssm_Device), "xpkdisk.device") == 0;
  486.  
  487.     RootBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
  488.     if (RootBlock == NULL)
  489.     return 6;
  490.  
  491.     BitmapBlock = AllocMem(2 * SIZE * sizeof(ULONG), De.de_BufMemType);
  492.     if (BitmapBlock == NULL)
  493.     return 7;
  494.  
  495.     BitmapExtBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
  496.     if (BitmapExtBlock == NULL)
  497.     return 8;
  498.  
  499.     ZeroBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
  500.     if (ZeroBlock == NULL)
  501.     return 9;
  502.  
  503.     LowTrack = De.de_Surfaces * De.de_LowCyl;
  504.     Offset = sizeof(ULONG) * SIZE * De.de_BlocksPerTrack * LowTrack;
  505.     NumTracks = De.de_Surfaces * (De.de_HighCyl - De.de_LowCyl + 1);
  506.     MaxKey = De.de_BlocksPerTrack * NumTracks;
  507.     RootBlockKey = (MaxKey - 1 + De.de_Reserved) / 2;
  508.  
  509.     BitsPerBitmapBlock = 32 * (SIZE - 1);
  510.  
  511.     debug0(("Offset %x, RootBlockKey %d\n", Offset, RootBlockKey));
  512.     debug0(("Bits/BitmapBlock %d\n", BitsPerBitmapBlock));
  513.  
  514.     if (De.de_BlocksPerTrack > BitsPerBitmapBlock) {
  515.     printf(
  516. "What a funny disk you have! %d blocks/track is more than I can handle!\n",
  517.         De.de_BlocksPerTrack);
  518.     return 10;
  519.     }
  520.  
  521.     return 0;
  522. }
  523.  
  524. void
  525. CloseAll(void)
  526. {
  527.     if (RootBlock)
  528.     FreeMem(RootBlock, SIZE * sizeof(unsigned long));
  529.     if (BitmapBlock)
  530.     FreeMem(BitmapBlock, 2 * SIZE * sizeof(unsigned long));
  531.     if (BitmapExtBlock)
  532.     FreeMem(BitmapExtBlock, SIZE * sizeof(unsigned long));
  533.     if (ZeroBlock)
  534.     FreeMem(ZeroBlock, SIZE * sizeof(unsigned long));
  535.     if (Io) {
  536.     if (Io->iotd_Req.io_Device) {
  537.         Io->iotd_Req.io_Command = CMD_UPDATE;    /* ETD */
  538.         DoIO((struct IORequest *)Io);
  539.         Io->iotd_Req.io_Command = TD_MOTOR;
  540.         Io->iotd_Req.io_Length = 0;
  541.         DoIO((struct IORequest *)Io);
  542.         CloseDevice((struct IORequest *)Io);
  543.     }
  544.     DeleteExtIO((struct IORequest *)Io);
  545.     }
  546.     if (Port)
  547.     DeleteMsgPort(Port);
  548.     if (HandlerPort) {
  549.     DoPkt(HandlerPort, ACTION_INHIBIT, 0, 0, 0, 0, 0);
  550.     }
  551.  
  552.     printf(
  553. "Statistics: %d (%d) sectors (really) cleared,\n"
  554. "            %d (%d) tracks (really) deleted, \n"
  555. "            %d free sectors total.\n",
  556.         SectorsCleared,
  557.         SectorsReallyCleared,
  558.         TracksDeleted,
  559.         TracksReallyDeleted,
  560.         SectorsCleared + TracksDeleted * De.de_BlocksPerTrack);
  561. }
  562.  
  563. int
  564. main(int argc, char **argv)
  565. {
  566.     char       *colon;
  567.     int         ac;
  568.     char      **av;
  569.  
  570.     if (DOSBase->dl_lib.lib_Version < 37) {
  571.     printf("Sorry, requires 2.04+ (V37+)\n");
  572.     return 20;
  573.     }
  574.  
  575.     ac = argc - 1;
  576.     av = argv + 1;
  577.  
  578.     while (ac > 0 && av[0][0] == '-') {
  579.     char           *a = av[0] + 1;
  580.  
  581.     while (a[0]) {
  582.         switch (a[0]) {
  583.         case 'n':
  584.         Pretend = 1;
  585.         printf("Pretend mode.\n");
  586.         break;
  587.         case 'v':
  588.         Verbose++;
  589.         break;
  590.         default:
  591.         goto usage;
  592.         }
  593.         a++;
  594.     }
  595.     ac--;
  596.     av++;
  597.     }
  598.  
  599.     if (ac < 1) {
  600.     usage:
  601.     printf("Usage: %s [-n] [-v] devicename\n", argv[0]);
  602.     return 20;
  603.     }
  604.  
  605.     if (colon = strchr(av[0], ':'))
  606.     *colon = '\0';
  607.  
  608.     atexit(CloseAll);
  609.  
  610.     if (OpenAll(av[0]) == 0) {
  611.     if (!Pretend) {
  612.         printf("Hit return to commence clearing %s: or CTRL-C to abort: ",
  613.             av[0]);
  614.         fflush(stdout);
  615.         while (!feof(stdin) && getchar() != '\n')
  616.         /* nothing */ ;
  617.         chkabort();
  618.     }
  619.     Clear();
  620.     }
  621.     /*CloseAll();*/
  622.  
  623.     return 0;
  624. }
  625.